import org.molamil.acto.props.PropHrefPointer;
import org.molamil.acto.core.Dispatcher;

import mx.events.EventDispatcher;

import org.molamil.acto.core.Logger;
import org.molamil.acto.commands.cmd.XmlParseCmd;
import org.molamil.acto.commands.CommandContext;
import org.molamil.acto.core.EventConstants;
import org.molamil.acto.commands.CommandRequest;
import org.molamil.acto.props.PropsParser;

import mx.utils.Delegate;

import org.molamil.acto.props.PropWrapper;
import org.molamil.acto.props.PropLoader;


/**
 * @author Jorge Hernandez
 */
class org.molamil.acto.props.PropValueResolver implements PropLoader {

	
	// Properties
	
	private static var log:Logger = Logger.getLogger("PropValueResolver");
	
	private var resolveHrefObject:Object;	private var isRecursiveHref:Boolean;	private var hrefProps:Array;	private var hrefPropsLoadStartCount:Number;	private var hrefPropsLoadCompleteCount:Number;
	
		// Constructor
	
	public function PropValueResolver() {
		hrefProps = new Array();
		hrefPropsLoadStartCount = 0;		hrefPropsLoadCompleteCount = 0;
		EventDispatcher.initialize(this);
	}

	
	// Functions
	
	public function dispatchEvent(eventObj:Object):Void {}
	public function addEventListener(event:String, handler):Void {}
	public function removeEventListener(event:String, handler):Void {}
	
	public function resolveHref(o:Object):Object {
		
		log.debug("resolveHref()");
			
		resolveHrefObject = o;
		
		hrefPropsLoadStartCount = 0;
		hrefPropsLoadCompleteCount = 0;
		
		hrefProps = new Array();
		hrefProps = getHrefProps(o);
		
		log.debug("resolveHref(), found: " + hrefProps.length);
		
		for (var i:Number = 0; i < hrefProps.length; i++) {
			var propWrapper:PropWrapper = PropWrapper(hrefProps[i]);			var pointer:PropHrefPointer = PropHrefPointer(propWrapper.value);
			pointer.loader = this;
			var cmdContext:CommandContext = new CommandContext();
			cmdContext.target = pointer.href;			cmdContext.props.cmd = {parser: PropsParser};			cmdContext.props._propWrapper = propWrapper;			cmdContext.props._pointer = pointer;
			var cmdRequest:CommandRequest = new CommandRequest();
			var cmd:XmlParseCmd = new XmlParseCmd(cmdContext);
			cmd.addEventListener(EventConstants.COMMAND_EXECUTE_START, Delegate.create(this, onCmdExecuteStart));			cmd.addEventListener(EventConstants.COMMAND_EXECUTE_COMPLETE, Delegate.create(this, onCmdExecuteComplete));			cmd.addEventListener(EventConstants.COMMAND_EXECUTE_ERROR, Delegate.create(this, onCmdExecuteError));
			cmd.execute(cmdRequest);
		}
		
		log.info("resolveHref(), PROPS LOAD START");
		dispatchEvent({target: this, type: EventConstants.PROPS_LOAD_START});
		
		if (hrefProps.length == 0)
			doPropsLoadComplete();
			
		return null;
		
	}
	
	private function getHrefProps(prop:Object, name:String, parent:Object):Array {
		
		log.debug("getHrefProps()");
		
		if (parent != null && prop instanceof PropHrefPointer) {
			var propWrapper:PropWrapper = new PropWrapper(name, prop, parent);
			hrefProps.push(propWrapper);
			log.debug("getHrefProps(), adding href, length: " + hrefProps.length);
		} else {
			for (var p:String in prop) {
				log.debug("getHrefProps(), href resolving: " + p);
				getHrefProps(prop[p], p, prop);
			}
		}
			
		return hrefProps;
		
	}
	
	private function doPropsLoadComplete():Void {
		log.info("doPropsLoadComplete(), PROPS LOAD COMPLETE (no properties to load)");
		dispatchEvent({target: this, type: EventConstants.PROPS_LOAD_COMPLETE});
	}
	
	private function onCmdExecuteStart(eventObject:Object):Void {
		
		var cmd:XmlParseCmd = XmlParseCmd(eventObject.target);
		
		log.debug("onCmdExecuteStart(): " + cmd.context.target);
		
		hrefPropsLoadStartCount++;
		
		log.debug("onCmdExecuteStart(), hrefPropsLoadCount = " + hrefPropsLoadStartCount);
		
		dispatchEvent({target: cmd.context.props._pointer, type: EventConstants.PROP_LOAD_START});
		
	}
	
	private function onCmdExecuteComplete(eventObject:Object):Void {
		
		var cmd:XmlParseCmd = XmlParseCmd(eventObject.target);
		
		log.debug("onCmdExecuteComplete(): " + cmd.context.target);		log.debug("onCmdExecuteComplete(), result: " + cmd.result.result);
		
		var propWrapper:PropWrapper = PropWrapper(cmd.context.props._propWrapper);
		propWrapper.value = eventObject.result;
		propWrapper.applyValue();
		
		hrefPropsLoadCompleteCount++;
		
		if (hrefPropsLoadCompleteCount == hrefProps.length) {
			
			log.info("onCmdExecuteComplete(), all commands completed");
			
			var propResolver:PropValueResolver = new PropValueResolver();
			propResolver.addEventListener(EventConstants.PROPS_LOAD_COMPLETE, Delegate.create(this, doPropsLoadComplete));
			propResolver.resolveHref(resolveHrefObject);
			
		}
		
		dispatchEvent({target: cmd.context.props._pointer, type: EventConstants.PROP_LOAD_COMPLETE});
		
	}
	
	private function onCmdExecuteError(eventObject:Object):Void {
		
		var cmd:XmlParseCmd = XmlParseCmd(eventObject.target);
		
		log.severe("onCmdExecuteError(): " + cmd.context.target);
		
		dispatchEvent({target: cmd.context.props._pointer, type: EventConstants.PROP_LOAD_ERROR});
		
	}
	
	
}
